This passes RUSTFLAGS to rustc builds for the target architecture.
We don't want to pass the RUSTFLAGS args to multiple architectures because
they may contain architecture-specific flags. Ideally, the scheme
we would use would treat plugins and build scripts - which may not
be for the target architecture - consistently. Unfortunately it's
quite difficult in the current Cargo architecture to seperately
identify build scripts, plugins and their dependencies from
code used by the target.
So the scheme here is very simple:
1) If --target is not specified, RUSTFLAGS applies to all builds.
2) If --target is specified, RUSTFLAGS only applies to builds
with the Kind::Target target kind, which indicates build units
derived from the requested --target.
Closes #2112
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libgit2-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.1.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.55 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "aho-corasick"
-version = "0.4.1"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "gcc 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "gcc 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.6.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "regex 0.1.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.55 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.1.48 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.55 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "gcc"
-version = "0.3.23"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "num 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cmake 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "gcc 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "memchr"
-version = "0.1.7"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "gcc 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nom"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num"
-version = "0.1.30"
+version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "num_cpus"
-version = "0.2.10"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
-version = "0.3.6"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "regex"
-version = "0.1.48"
+version = "0.1.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "aho-corasick 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
-version = "0.2.2"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "semver"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "nom 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nom 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "tar"
-version = "0.4.3"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "utf8-ranges"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "uuid"
version = "0.1.18"
use std::collections::{HashSet, HashMap};
+use std::env;
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
use std::sync::Arc;
target_info: TargetInfo,
host_info: TargetInfo,
profiles: &'a Profiles,
+ rustflags: Option<String>,
}
#[derive(Clone)]
let engine = build_config.exec_engine.as_ref().cloned().unwrap_or({
Arc::new(Box::new(ProcessEngine))
});
+ let rustflags = env::var("RUSTFLAGS").ok();
Ok(Context {
target_triple: target_triple,
host: host,
build_scripts: HashMap::new(),
build_explicit_deps: HashMap::new(),
links: Links::new(),
+ rustflags: rustflags,
})
}
// profile? How is this controlled at the CLI layer?
&self.profiles.dev
}
+
+ pub fn rustflags_args(&self, unit: &Unit) -> Vec<String> {
+ // We *want* to apply RUSTFLAGS only to builds for the
+ // requested target architecture, and not to things like build
+ // scripts and plugins, which may be for an entirely different
+ // architecture. Cargo's present architecture makes it quite
+ // hard to only apply flags to things that are not build
+ // scripts and plugins though, so we do something more hacky
+ // instead to avoid applying the same RUSTFLAGS to multiple targets
+ // arches:
+ //
+ // 1) If --target is not specified we just apply RUSTFLAGS to
+ // all builds; they are all going to have the same target.
+ //
+ // 2) If --target *is* specified then we only apply RUSTFLAGS
+ // to compilation units with the Target kind, which indicates
+ // it was chosen by the --target flag.
+ //
+ // This means that, e.g. even if the specified --target is the
+ // same as the host, build scripts in plugins won't get
+ // RUSTFLAGS.
+ let compiling_with_target = self.build_config.requested_target.is_some();
+ let is_target_kind = unit.kind == Kind::Target;
+ let use_rustflags = match (compiling_with_target, is_target_kind) {
+ (false, _) => true,
+ (true, true) => true,
+ (true, false) => false,
+ };
+
+ if !use_rustflags { return Vec::new(); }
+
+ let mut args = Vec::new();
+
+ if let Some(ref a) = self.rustflags {
+ for s in a.split(" ") {
+ args.push(s.to_owned());
+ }
+ }
+
+ args
+ }
}
let dep_info_loc = fingerprint::dep_info_loc(cx, unit);
let cwd = cx.config.cwd().to_path_buf();
- return Ok(Work::new(move |desc_tx| {
- debug!("about to run: {}", rustc);
+ let rustflags = cx.rustflags_args(unit);
+ return Ok(Work::new(move |desc_tx| {
// Only at runtime have we discovered what the extra -L and -l
// arguments are for native libraries, so we process those here. We
// also need to be sure to add any -L paths for our plugins to the
}
}
+ // Add the arguments from RUSTFLAGS
+ rustc.args(&rustflags);
+
desc_tx.send(rustc.to_string()).ok();
try!(exec_engine.exec(rustc).chain_error(|| {
human(format!("Could not compile `{}`.", name))
assert_that(p.cargo_process("build").arg("-v"),
execs().with_status(0));
});
+
+test!(rustflags_normal_source {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#);
+ p.build();
+
+ // Use RUSTFLAGS to pass an argument that will generate an error
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--lib"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--bin=a"),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--bin=b"),
+ execs().with_status(101));
+ assert_that(p.cargo("check").env("RUSTFLAGS", "-Z bogus"),
+ execs().with_status(101));
+ assert_that(p.cargo("bench").env("RUSTFLAGS", "-Z bogus"),
+ execs().with_status(101));
+});
+
+test!(rustflags_build_script {
+ // RUSTFLAGS should be passed to rustc for build scripts
+ // when --target is not specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ #[cfg(not(foo))]
+ fn main() { }
+ "#);
+ p.build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+});
+
+test!(rustflags_build_script_dep {
+ // RUSTFLAGS should be passed to rustc for build scripts
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+
+ [build-dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ "#);
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(not(foo))]
+ fn bar() { }
+ "#);
+ foo.build();
+ bar.build();
+
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+});
+
+test!(rustflags_plugin {
+ // RUSTFLAGS should be passed to rustc for plugins
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ fn main() { }
+ #[cfg(not(foo))]
+ fn main() { }
+ "#);
+ p.build();
+
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+});
+
+test!(rustflags_plugin_dep {
+ // RUSTFLAGS should be passed to rustc for plugins
+ // when --target is not specified.
+ // In this test if --cfg foo is not passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn foo() { }
+ "#);
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(not(foo))]
+ fn bar() { }
+ "#);
+ foo.build();
+ bar.build();
+
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo"),
+ execs().with_status(0));
+});
+
+test!(rustflags_normal_source_with_target {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", "")
+ .file("src/bin/a.rs", "fn main() {}")
+ .file("examples/b.rs", "fn main() {}")
+ .file("tests/c.rs", "#[test] fn f() { }")
+ .file("benches/d.rs", r#"
+ #![feature(test)]
+ extern crate test;
+ #[bench] fn run1(_ben: &mut test::Bencher) { }"#);
+ p.build();
+
+ let ref host = ::rustc_host();
+
+ // Use RUSTFLAGS to pass an argument that will generate an error
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--lib").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--bin=a").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("build").env("RUSTFLAGS", "-Z bogus")
+ .arg("--bin=b").arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("check").env("RUSTFLAGS", "-Z bogus")
+ .arg("--target").arg(host),
+ execs().with_status(101));
+ assert_that(p.cargo("bench").env("RUSTFLAGS", "-Z bogus")
+ .arg("--target").arg(host),
+ execs().with_status(101));
+});
+
+test!(rustflags_build_script_with_target {
+ // RUSTFLAGS should not be passed to rustc for build scripts
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ #[cfg(foo)]
+ fn main() { }
+ "#);
+ p.build();
+
+ let host = ::rustc_host();
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+});
+
+test!(rustflags_build_script_dep_with_target {
+ // RUSTFLAGS should not be passed to rustc for build scripts
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ build = "build.rs"
+
+ [build-dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", r#"
+ fn main() { }
+ "#);
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(foo)]
+ fn bar() { }
+ "#);
+ foo.build();
+ bar.build();
+
+ let host = ::rustc_host();
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+});
+
+test!(rustflags_plugin_with_target {
+ // RUSTFLAGS should not be passed to rustc for plugins
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+ "#)
+ .file("src/lib.rs", r#"
+ fn main() { }
+ #[cfg(foo)]
+ fn main() { }
+ "#);
+ p.build();
+
+ let host = ::rustc_host();
+ assert_that(p.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+});
+
+test!(rustflags_plugin_dep_with_target {
+ // RUSTFLAGS should not be passed to rustc for plugins
+ // when --target is specified.
+ // In this test if --cfg foo is passed the build will fail.
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [lib]
+ name = "foo"
+ plugin = true
+
+ [dependencies.bar]
+ path = "../bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn foo() { }
+ "#);
+ let bar = project("bar")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+
+ [lib]
+ name = "bar"
+ "#)
+ .file("src/lib.rs", r#"
+ fn bar() { }
+ #[cfg(foo)]
+ fn bar() { }
+ "#);
+ foo.build();
+ bar.build();
+
+ let host = ::rustc_host();
+ assert_that(foo.cargo("build").env("RUSTFLAGS", "--cfg foo")
+ .arg("--target").arg(host),
+ execs().with_status(0));
+});